
#include "controller_types.h"
#include "user_table.h"

#include "FreeRTOS.h"
#include "queue.h"
#include "semphr.h"
#include "task.h"
#include "timers.h"


#include "Driver.h"
#include "DeviceLight.h"
#include "Door.h"

#define CTRL_RES_ERROR	-1
#define CTRL_RES_NONE	0
#define CTRL_RES_OK		0x01
#define CTRL_RES_OPEN	0x02


typedef struct _controller{
	TimerHandle_t timer;
	user_info_t cur_user;
	int8_t tick;
	uint8_t state;
	uint8_t input_length;
	uint8_t input_buffer[16];
}controller_t;

static controller_t controller;

static user_info_t test_user = {
	.pin = 1,
	.card = {
		.len = 4, 
		.data = {0xB6, 0xA7, 0xCF, 0x78},
	},
	.pwd = {
		.len = 4, 
		.data = {1, 2, 3, 4},
	},
};

static void controller_timer_cb(xTimerHandle timer){
	if(controller.tick > 0){
		controller.tick--;
	}
}

int controller_init(void){
	user_table_init();
	user_table_update_user(&test_user);
	controller.timer = xTimerCreate("ctrl", 1000, pdTRUE, NULL, controller_timer_cb);
	xTimerStart(controller.timer, portMAX_DELAY);
	controller.tick = -1;
	return 0;
}

int controller_update_user( user_info_t* user){
	return user_table_update_user(user);
}

static int cmp_pin(const void* tk, const user_info_t* u){
	user_pin_t pin = (user_pin_t)tk;
	if(pin != u->pin){
		return 0;
	}
	return 1;
}

static inline int cmp_token(const user_token_t* t1, const user_token_t* t2){
	if(t1->len != t2->len){
		return 0;
	}
	if(memcmp(t1->data, t2->data, t2->len)){
		return 0;
	}
	return 1;
}

static int cmp_card(const void* tk, const user_info_t* u){
	return cmp_token((const user_token_t*)tk, &u->card);
}

static int cmp_pwd(const void* tk, const user_info_t* u){
	return cmp_token((const user_token_t*)tk, &u->pwd);
}


int controller_find_user_by_pin(user_pin_t pin, user_info_t* user){
	return user_table_find((const void *) pin, cmp_pin, user, NULL);
}

int controller_find_user_by_token(uint8_t type, const user_token_t* token, user_info_t* user){
	int ret;
	
	if(type == EV_T_Card){
		ret = user_table_find((const void *) token, cmp_card, user, NULL);
	}
	else{
		ret = user_table_find((const void *) token, cmp_pwd, user, NULL);
	}
	
	return ret;
}

int controller_remove_user_by_pin(user_pin_t pin){
	uint32_t index = 0;
	int ret = user_table_find((const void *) pin, cmp_pin, NULL, &index);
	if(ret){
		return 0;
	}
	
	return user_table_erase(index);
}

int controller_remove_user_by_token(uint8_t type, const user_token_t* token){
	uint32_t index = 0;
	int ret;
	
	if(type == EV_T_Card){
		ret = user_table_find((const void *) token, cmp_card, NULL, &index);
	}
	else{
		ret = user_table_find((const void *) token, cmp_pwd, NULL, &index);
	}
	
	if(ret){
		return 0;
	}
	
	return user_table_erase(index);
}

/*-----------------------------------------------------------------------------------------------*/
static uint32_t controller_buffer_to_uint32(controller_t* ctrl){
	uint32_t n = 0;
	
	for(int i = 0; i < ctrl->input_length; i++){
		n *= 10;
		n += ctrl->input_buffer[i];
	}

	return n;
}


static int controller_verify_token(controller_t* ctrl, uint8_t type, const user_token_t* token){
	int ret;
	
	if(type == EV_T_Card){
		ret = user_table_find((const void *) token, cmp_card, &ctrl->cur_user, NULL);
	}
	else{
		ret = user_table_find((const void *) token, cmp_pwd, &ctrl->cur_user, NULL);
	}
	if(ret){
		return ret;
	}
	//TODO:校验有效期
	
	return ret;
}

static inline user_token_t* user_token_build(user_token_t* tk, uint8_t len, const void* data){
	tk->len = len;
	memcpy(tk->data, data, len);
	return tk;
}

static int controller_input_event_card(controller_t* ctrl, const input_event_t* event){
	user_token_t token;
	if(controller_verify_token(ctrl, event->type, user_token_build(&token, event->len, event->data)) == 0){
		return CTRL_RES_OK|CTRL_RES_OPEN;
	}
	return CTRL_RES_ERROR;
}

#define event_is_key_num(e)	(e)->
static inline int controller_even_key_is_num(const input_event_t* event){
	return event->data[0] < 10;
}

static void controller_reset(controller_t* ctrl){
	ctrl->tick = -1;
	ctrl->input_length = 0;
	ctrl->state = 0;
}

static int controller_process_key(controller_t* ctrl){
	if(ctrl->state == 0){
		if(ctrl->input_length){
			//输入密码
			user_token_t token;
			if(controller_verify_token(ctrl, EV_T_Key, user_token_build(&token, ctrl->input_length, ctrl->input_buffer)) == 0){
				return CTRL_RES_OK|CTRL_RES_OPEN;
			}
			return CTRL_RES_ERROR;
		}
		else{
			//进入控制
			ctrl->state = 1;
		}
		return CTRL_RES_NONE;
	}
	
	if(ctrl->input_length == 0){
		return CTRL_RES_NONE;
	}
	
	switch(ctrl->state){
#if 0
	case 0:{
		if(ctrl->input_length){
			//输入密码
			user_token_t token;
			if(controller_verify_token(ctrl, EV_T_Key, user_token_build(&token, ctrl->input_length, ctrl->input_buffer)) == 0){
				return 1;
			}
			return -1;
		}
		else{
			//进入控制
			ctrl->state = 1;
		}
	}
	break;
#endif 
	case 1:{
		//输入密码，进入设置模式
		user_token_t token;
		if(controller_verify_token(ctrl, EV_T_Key, user_token_build(&token, ctrl->input_length, ctrl->input_buffer)) == 0){
			ctrl->state = 2;
		}
		else{
			return CTRL_RES_ERROR;
		}
	}
	break;
	case 2:{
		//选择设置功能
		uint8_t op = controller_buffer_to_uint32(ctrl);
		switch(op){
		case 1:{
			ctrl->state = 3;
		}
		break;
		case 11:{
			if(ctrl->cur_user.flag & USER_F_ADMIN){
				ctrl->state = 10;
			}
			else{
				return CTRL_RES_ERROR;
			}
		}
		break;
		default:
			return CTRL_RES_ERROR;
		}
	}
	break;
	case 3:{
		user_token_build(&ctrl->cur_user.pwd, ctrl->input_length, ctrl->input_buffer);
		ctrl->state = 4;
	}
	break;
	case 4:{
		user_token_t token;
		user_token_build(&token, ctrl->input_length, ctrl->input_buffer);
		if(cmp_pwd(&token, &ctrl->cur_user)){
			if(controller_update_user(&ctrl->cur_user) == 0){
				return CTRL_RES_OK;
			}
			return CTRL_RES_ERROR;
		}
		else{
			return CTRL_RES_ERROR;
		}
	}
	break;
	case 10:{
		user_pin_t pin = controller_buffer_to_uint32(ctrl);
		if(controller_find_user_by_pin(pin, &ctrl->cur_user) == 0){
			ctrl->state = 11;
		}
		else{
			return CTRL_RES_ERROR;
		}
	}
	break;
	case 11:{
		user_token_build(&ctrl->cur_user.pwd, ctrl->input_length, ctrl->input_buffer);
		if(controller_update_user(&ctrl->cur_user) == 0){
			return CTRL_RES_OK;
		}
		return CTRL_RES_ERROR;
	}
	break;
	}
	
	return CTRL_RES_NONE;
}

//处理按键输入
static int controller_input_event_key(controller_t* ctrl, const input_event_t* event){
	if(controller_even_key_is_num(event)){
		//数字按键
		if(ctrl->input_length < sizeof(ctrl->input_buffer)){
			ctrl->input_buffer[ctrl->input_length++] = event->data[0];
		}
		else{
			//缓存溢出
			ctrl->input_length = 0;
			return CTRL_RES_ERROR;
		}
	}
	else{
		//控制按键
		if(event->data[0] == 0x0B){
			// 键 '#'
			int ret = controller_process_key(ctrl);
			ctrl->input_length = 0;
			return ret;
		}
		else{
			//键'*'
			if(ctrl->input_length > 0){
				//清空缓存
				ctrl->input_length = 0;
			}
			else{
				//缓存已清空，则恢复空闲状态
				controller_reset(ctrl);
			}
		}
	}
	return CTRL_RES_NONE;
}

void controller_input_event(const input_event_t* event){
	int ret = 0;
	controller.tick = 10;
	if(event->type == EV_T_Card){
		ret = controller_input_event_card(&controller, event);
	}
	else
	if(event->type == EV_T_Key){
		ret = controller_input_event_key(&controller, event);
	}

	if(ret > 0){
		//成功，开门
		if(ret & CTRL_RES_OK){
			DeviceLight_Flash(1, Color_Green, 1000);
			Buzzer_AsyncBeep(200);
		}
		if(ret & CTRL_RES_OPEN){
			Door_TempSwitch(1000);
		}
		controller_reset(&controller);
	}
	else
	if(ret < 0){
		//失败，提示
		Buzzer_BeepDuration(3, 100);
		controller_reset(&controller);
	}
	else{
		//继续，无动作
	}
}

void controller_service(void){
	if(controller.tick == 0){
		controller.tick = -1;
		Buzzer_BeepDuration(3, 100);
		controller_reset(&controller);
	}
}

